package com.abou.connector.dao.impl.product;

import java.util.List;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.abou.connector.dao.IGenericDao;
import com.abou.connector.dao.IProductDao;
import com.abou.connector.dao.impl.AGenericDaoImpl;
import com.abou.constant.product.ECategory;
import com.abou.constant.product.EClotheType;
import com.abou.constant.product.EProductType;
import com.abou.constant.product.ESortOrder;
import com.abou.model.common.product.Product;

/**
 * @see IGenericDao
 * @author khalid
 */
@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class ProductDaoImpl extends AGenericDaoImpl<Product> implements
    IProductDao {
  
  /**
   * The startRow attribute name
   */
  protected static final String START_ROW_ATT = "startRow";
  
  /**
   * The endRow attribute name
   */
  protected static final String END_ROW_ATT = "endRow";
  
  /**
   * The name attribute name
   */
  protected static final String NAME_ATT = "name";
  
  /**
   * The sort order attribute name
   */
  protected static final String SORT_ORDER_ATT = "sordOrder";
  
  /**
   * The description attribute name
   */
  protected static final String DESCRIPTION_ATT = "description";
  
  /**
   * The type attribute name
   */
  protected static final String TYPE_ATT = "productType";
  
  /**
   * The type attribute name
   */
  protected static final String CAT_ATT = "category";
  
  /**
   * The type attribute name
   */
  protected static final String CLOTHE_ATT = "clotheType";
  
  /**
   * The empty constructor
   */
  public ProductDaoImpl() {

    super();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByDescription(java.lang.String,
   *      com.abou.constant.product.ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductByDescription(String description,
      ESortOrder sortOrder, int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductByDescriptionAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductByDescriptionDesc");
    }
    
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByName(String,
   *      ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductByName(String name, ESortOrder sortOrder,
      int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query =
          getEntityManager().createNamedQuery("Product.findProductByNameAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery("Product.findProductByNameDesc");
    }
    
    query.setParameter(NAME_ATT, "%" + name + "%");
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByType(com.abou.constant.product.EProductType,
   *      com.abou.constant.product.ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductByType(EProductType type,
      ESortOrder sortOrder, int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query =
          getEntityManager().createNamedQuery("Product.findProductByTypeAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery("Product.findProductByTypeDesc");
    }
    
    query.setParameter(TYPE_ATT, type);
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProducts(java.lang.String,
   *      java.lang.String, com.abou.constant.product.EProductType,
   *      com.abou.constant.product.ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProducts(String name, String description,
      EProductType type, ESortOrder sortOrder, int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query = getEntityManager().createNamedQuery("Product.findProductsAsc");
      
    } else {
      
      query = getEntityManager().createNamedQuery("Product.findProductsDesc");
    }
    
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, type);
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findAllProducts(com.abou.constant.product.ESortOrder,
   *      int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findAllProducts(ESortOrder sortOrder, int pageIndex,
      int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query = getEntityManager().createNamedQuery("Product.findAllProductsAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery("Product.findAllProductsDesc");
    }
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findAllProducts()
   */
  public int findAllProducts() {

    Query query =
        getEntityManager().createNamedQuery("Product.findAllProductsDesc");
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByDescription(java.lang.String)
   */
  public int findProductByDescription(String description) {

    Query query =
        getEntityManager().createNamedQuery(
            "Product.findProductByDescriptionDesc");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByName(java.lang.String)
   */
  public int findProductByName(String name) {

    Query query =
        getEntityManager().createNamedQuery("Product.findProductByNameDesc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductByType(com.abou.constant.product.EProductType)
   */
  public int findProductByType(EProductType type) {

    Query query =
        getEntityManager().createNamedQuery("Product.findProductByTypeDesc");
    query.setParameter(TYPE_ATT, type);
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProducts(java.lang.String,
   *      java.lang.String, com.abou.constant.product.EProductType)
   */
  public int findProducts(String name, String description, EProductType type) {

    Query query =
        getEntityManager().createNamedQuery("Product.findProductsDesc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, type);
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsByNameDescription(java.lang.String,
   *      java.lang.String, com.abou.constant.product.ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductsByNameDescription(String name,
      String description, ESortOrder sortOrder, int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductsByNameDescriptionAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductsByNameDescriptionDesc");
    }
    
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsByNameDescription(java.lang.String,
   *      java.lang.String)
   */
  public int findProductsByNameDescription(String name, String description) {

    Query query =
        getEntityManager().createNamedQuery(
            "Product.findProductsByNameDescriptionAsc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsClothes(java.lang.String,
   *      java.lang.String, com.abou.constant.product.ECategory,
   *      com.abou.constant.product.EClotheType,
   *      com.abou.constant.product.ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductsClothes(String name, String description,
      EProductType productType, EClotheType clotheType, ESortOrder sortOrder,
      int pageIndex, int pageSize) {

    Query query = null;
    
    if (sortOrder == ESortOrder.ASC) {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductsForClothesAsc");
      
    } else {
      
      query =
          getEntityManager().createNamedQuery(
              "Product.findProductsForClothesDesc");
    }
    
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, productType);
    query.setParameter(CLOTHE_ATT, clotheType);
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsClothes(java.lang.String,
   *      java.lang.String, com.abou.constant.product.ECategory,
   *      com.abou.constant.product.EClotheType)
   */
  public int findProductsClothes(String name, String description,
      EProductType productType, EClotheType clotheType) {

    Query query =
        getEntityManager().createNamedQuery("Product.findProductsForClothesAsc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, productType);
    query.setParameter(CLOTHE_ATT, clotheType);
    
    return query.getResultList().size();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsClothesNoClotheType(String,
   *      String, ECategory, ESortOrder, int, int)
   */
  @SuppressWarnings("unchecked")
  public List<Product> findProductsClothesNoClotheType(String name,
      String description, EProductType productType, ESortOrder sortOrder,
      int pageIndex, int pageSize) {

    Query query =
        getEntityManager().createNamedQuery(
            "Product.findProductsForClothesNoClotheTypeAsc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, productType);
    
    // pagination
    query.setFirstResult(pageIndex * pageSize);
    query.setMaxResults(pageSize);
    
    return query.getResultList();
  }
  
  /**
   * @see com.abou.connector.dao.IProductDao#findProductsClothesNoClotheType(String,
   *      String, ECategory)
   */
  public int findProductsClothesNoClotheType(String name, String description,
      EProductType productType) {

    Query query =
        getEntityManager().createNamedQuery(
            "Product.findProductsForClothesNoClotheTypeAsc");
    query.setParameter(NAME_ATT, "%" + name + "%");
    query.setParameter(DESCRIPTION_ATT, "%" + description + "%");
    query.setParameter(TYPE_ATT, productType);
    
    return query.getResultList().size();
  }
  
}